package com.dayatang.hrm.compensation.domain;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.springframework.beans.BeanUtils;
import org.springframework.context.support.MessageSourceAccessor;

import com.dayatang.commons.domain.AbstractEntity;
import com.dayatang.commons.domain.InstanceFactory;
import com.dayatang.hrm.compensation.context.CompensationMessageSource;
import com.dayatang.hrm.compensation.domain.exception.CompensationRuntimeException;
import com.dayatang.hrm.compensation.utils.DateVersionUtils;
import com.dayatang.hrm.staffing.domain.Employee;
import com.dayatang.utils.DateUtils;

@Entity
@Table(name = "pay_cal_rule_setting")
@NamedQueries( { @NamedQuery(name = "CalculateRuleSetting.get", query = "select setting from CalculateRuleSetting setting inner join setting.calculateRule o where (o = :pRule and setting.fromDate <= :pQueryDate and setting.toDate >= :pQueryDate)") })
public class CalculateRuleSetting extends AbstractEntity {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2314534518863480744L;

	private static CalculateRuleSettingRepository calculateRuleSettingRepository;

	protected static MessageSourceAccessor messages = CompensationMessageSource
			.getAccessor();

	// 规则属性
	@Column(name = "attribute_text", length = 500)
	private String attributeText;
	// 计算条件
	@Column(name = "condition_text", length = 500)
	private String conditionText;
	// 计算结果
	@Column(name = "consequence_text", length = 500)
	private String consequenceText;
	@Column(name = "is_need_tag_version")
	private Boolean needTagVersion;
	// 是否存在错误
	@Column(name = "is_error")
	private Boolean error;
	// 规则序号
	@Column(name = "rule_sequence")
	private Integer sequence;
	// 备注
	@Column(name = "remark", length = 200)
	private String remark;
	// 最后操作人
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "operator_id")
	private Employee operator;

	@Column(name = "from_date", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date fromDate;

	@Column(name = "to_date")
	@Temporal(TemporalType.TIMESTAMP)
	private Date toDate = DateUtils.MAX_DATE;

	// 创建时间
	@Column(name = "created_time")
	@Temporal(TemporalType.TIMESTAMP)
	private Date created;

	@ManyToOne
	@JoinColumn(name = "calculate_rule_id")
	private CalculateRule calculateRule;

	public CalculateRuleSetting() {
	}

	public CalculateRuleSetting(CalculateRule calculateRule) {
		this.calculateRule = calculateRule;
	}

	public static CalculateRuleSettingRepository getCalculateRuleSettingRepository() {
		if (calculateRuleSettingRepository == null) {
			calculateRuleSettingRepository = InstanceFactory
					.getInstance(CalculateRuleSettingRepository.class);
		}
		return calculateRuleSettingRepository;
	}

	public static void setCalculateRuleSettingRepository(
			CalculateRuleSettingRepository calculateRuleSettingRepository) {
		CalculateRuleSetting.calculateRuleSettingRepository = calculateRuleSettingRepository;
	}

	public String getAttributeText() {
		return attributeText;
	}

	public void setAttributeText(String attributeText) {
		this.attributeText = attributeText;
	}

	public String getConditionText() {
		return conditionText;
	}

	public void setConditionText(String conditionText) {
		this.conditionText = conditionText;
	}

	public String getConsequenceText() {
		return consequenceText;
	}

	public void setConsequenceText(String consequenceText) {
		this.consequenceText = consequenceText;
	}

	public Boolean isNeedTagVersion() {
		return needTagVersion;
	}

	public Boolean getNeedTagVersion() {
		return needTagVersion;
	}

	public void setNeedTagVersion(Boolean needTagVersion) {
		this.needTagVersion = needTagVersion;
	}

	public Boolean getError() {
		return error;
	}

	public void setError(Boolean error) {
		this.error = error;
	}

	public Integer getSequence() {
		return sequence;
	}

	public void setSequence(Integer sequence) {
		this.sequence = sequence;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public Employee getOperator() {
		return operator;
	}

	public void setOperator(Employee operator) {
		this.operator = operator;
	}

	public Date getCreated() {
		return created;
	}

	public void setCreated(Date created) {
		this.created = created;
	}

	public CalculateRule getCalculateRule() {
		return calculateRule;
	}

	public void setCalculateRule(CalculateRule calculateRule) {
		this.calculateRule = calculateRule;
	}

	public Date getFromDate() {
		return fromDate;
	}

	public void setFromDate(Date fromDate) {
		this.fromDate = fromDate;
	}

	public Date getToDate() {
		return toDate;
	}

	public void setToDate(Date toDate) {
		this.toDate = toDate;
	}

	@Override
	public boolean equals(Object arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * =======================================
	 * 
	 * action
	 * 
	 * ========================================
	 */

	private void save() {
		if (isNew()) {
			setCreated(new Date());

			if (fromDate == null) {
				setFromDate(created);
			}

			getCalculateRuleSettingRepository().save(this);
		} else {
			if (isNeedTagVersion()) {
				Date markedDate = new Date();

				// 取出原有设置
				CalculateRuleSetting setting = getPure(this);
				// 设置结束日期（MySQL不能精确到毫秒）
				setting.setToDate(DateVersionUtils
						.getPreviousVersionTimestamp(markedDate));
				getCalculateRuleSettingRepository().save(setting);

				// 作为新对象保存
				CalculateRuleSetting newInstance = new CalculateRuleSetting(
						calculateRule);
				BeanUtils.copyProperties(this, newInstance);
				newInstance.setId(null);
				newInstance.setFromDate(null);
				newInstance.setVersion(0);
				newInstance.setCreated(DateVersionUtils
						.getCurrentlyVersionTimestamp(markedDate));
				newInstance.save();
			} else {
				getCalculateRuleSettingRepository().save(this);
			}
		}
	}

	public void update() {
		if (isNew()) {
			throw new CompensationRuntimeException(messages.getMessage(
					"被更新的薪资计算公式设置不存在。",
					"CalculateRuleSetting.update.entityNotExist"));
		}
		getCalculateRuleSettingRepository().save(this);
	}

	/**
	 * 改正设置并保存（不会将设置备份）
	 */
	public void saveChanges() {
		// setNeedTagVersion(false);
		save();
	}

	/**
	 * 备份原有设置并保存当前设置（会将之前的设置备份）
	 */
	public void archive() {
		setNeedTagVersion(true);
		save();
	}

	public void markArchive() {
		setNeedTagVersion(true);
		update();
	}

	public void abolish(Date abolishDate) {
		if (abolishDate == null) {
			abolishDate = new Date();
		}
		setToDate(abolishDate);
		save();
	}

	public static CalculateRuleSetting init(CalculateRule calculateRule) {
		return new CalculateRuleSetting(calculateRule);
	}

	public static CalculateRuleSetting get(Long id) {
		return getCalculateRuleSettingRepository().get(id);
	}

	public static CalculateRuleSetting get(CalculateRule calculateRule,
			Date queryDate) {
		return getCalculateRuleSettingRepository()
				.get(calculateRule, queryDate);
	}

	public static CalculateRuleSetting getPure(
			CalculateRuleSetting calculateRuleSetting) {
		return getCalculateRuleSettingRepository()
				.getPure(calculateRuleSetting);
	}

}
